/* Copyright (c) 2007 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using Google.GData.Client;
using Google.GData.Documents;
using System.IO;
using System.Threading;

namespace DocListUploader
{
    public partial class OptionsForm : Form
    {
        //The parent form to this one.
        private HiddenForm mainForm;
        public Thread workerThread;
        public FileSystemWatcher FolderWatcher = new FileSystemWatcher();

        /// <summary>
        /// Constructor for the OptionsForm.
        /// </summary>
        /// <param name="mainForm">The parent form that created this one.</param>
        public OptionsForm(HiddenForm mainForm)
        {
            InitializeComponent();
            this.mainForm = mainForm;
            try
            {
                IntPtr handle = this.Handle; 
                readCredentials();
            }
            catch (Exception e) { }
        }

        public static Dictionary<string, string> GetProperties(string path)
        {
            string fileData = "";
            using (StreamReader sr = new StreamReader(path))
            {
                fileData = sr.ReadToEnd().Replace("\r", "");
            }
            Dictionary<string, string> Properties = new Dictionary<string, string>();
            string[] kvp;
            string[] records = fileData.Split("\n".ToCharArray());
            foreach (string record in records)
            {
                kvp = record.Split("=".ToCharArray());
                Properties.Add(kvp[0], kvp[1]);
            }
            return Properties;
        }


        public void readCredentials()
        {
    
            string applicationDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            string filename = applicationDataFolder + "\\iForture\\config";

            Dictionary<string, string> properties = GetProperties(filename);
            Username.Text = properties["username"];
            Password.Text = properties["password"];
            LoginButton_Click(this, null);
        }

        private void OptionsForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            //Don't destroy this form, just hide it.
            if(e.CloseReason == CloseReason.UserClosing) {
                this.Hide();
                mainForm.HandleMinimize();
                e.Cancel = true;
            }
        }

        private void LoginButton_Click(object sender, EventArgs e)
        {
            if (Username.Text == "")
            {
                MessageBox.Show("Please specify a username", "No user name", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (Password.Text == "")
            {
                MessageBox.Show("Please specify a password", "No password", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            try
            {
                LoginButton.Text = "Logging In";
                UploaderStatus.Text = "Connecting to server...";
                LoginButton.Enabled = false;
                LogoutButton.Enabled = true;
                //RefreshButton.Enabled = true;
                Username.Enabled = false;
                Password.Enabled = false;
                mainForm.Login(Username.Text, Password.Text);
                LoginButton.Text = "Logged In";
                UploaderStatus.Text = "Login complete";
                //UpdateDocList(); 
                

            }
            catch (Exception ex)
            {
                LoginButton.Enabled = true;
                LogoutButton.Enabled = false;
                Username.Enabled = true;
                Password.Enabled = true;
                //RefreshButton.Enabled = false;
                LoginButton.Text = "Login";
                UploaderStatus.Text = "Error authenticating";
                MessageBox.Show("Error logging into Google Docs: " + ex.Message, "Login Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

            // Create the thread object. This does not start the thread.
            FileUploader fu = new FileUploader(pendingFiles, CurrUpload, byteCounter, progressBar);
            fu.mainForm = mainForm;
            workerThread = new Thread(fu.DoWork);

            // Start the worker thread.
            workerThread.Start();
        }

        private void Username_KeyPress(object sender, KeyPressEventArgs e)
        {
            //If the user hits enter, skip to the next field.
            if (e.KeyChar == (char) 13)
            {
                Password.Focus();
            }
        }

        private void Password_KeyPress(object sender, KeyPressEventArgs e)
        {
            //If the user hits enter, try to log in.
            if (e.KeyChar == (char) 13)
            {
                LoginButton_Click(null, null);
            }
        }

        public bool IsFolder(string path)
        {
            return ((File.GetAttributes(path) & FileAttributes.Directory) == FileAttributes.Directory);
        }

        private void OptionsForm_DragDrop(object sender, DragEventArgs e)
        {
            if (!mainForm.loggedIn)
            {
                MessageBox.Show("Please log in before uploading documents", "Upload Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            string[] fileList = (string[]) e.Data.GetData(DataFormats.FileDrop);

            foreach (string file in fileList)
            {
                try
                {
                    if (IsFolder(file))
                    {
                        ListViewItem item = new ListViewItem(fileList[0]);
                        listViewFolders.Items.Add(item);
                        browseFolder(file);
                        startActivityMonitoring(file);
                    }
                    else
                    {
                        pendingFiles.Items.Add(file);
                    }
                }
                catch (ArgumentException)
                {
                    DialogResult result = MessageBox.Show("Error, unable to upload the file: '" + file + "'. It is not one of the valid types.", "Upload Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
                    UploaderStatus.Text = "Problems uploading";
                    if (result == DialogResult.Cancel)
                    {
                        return;
                    }
                }
                catch (Exception ex)
                {
                    DialogResult result = MessageBox.Show("Error, unable to upload the file: '" + file + "'. " + ex.Message, "Upload Error", MessageBoxButtons.OKCancel, MessageBoxIcon.Error);
                    UploaderStatus.Text = "Problems uploading";
                    if (result == DialogResult.Cancel)
                    {
                        return;
                    }
                }
            }

        }

        delegate void MyDelegate(string filename);
        public void addItem(string filename)
        {
            pendingFiles.Items.Add(filename);  
        }

        /// <summary>
        /// Triggered when an event is raised from the folder activity monitoring.
        /// All types exists in System.IO
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e">containing all data send from the event that got executed.</param>
        private void eventRaised(object sender, System.IO.FileSystemEventArgs e)
        {
            switch (e.ChangeType)
            {
                case WatcherChangeTypes.Changed:
                    pendingFiles.Invoke(new MyDelegate(addItem), e.FullPath);
                   
                    break;
                case WatcherChangeTypes.Created:
                    pendingFiles.Invoke(new MyDelegate(addItem), e.FullPath);

                    break;
                case WatcherChangeTypes.Deleted:
                    pendingFiles.Invoke(new MyDelegate(addItem), e.FullPath);

                    break;
                default: // Another action
                    break;
            }
        }


        private void startActivityMonitoring(string sPath)
        {
            // This is the path we want to monitor
            FolderWatcher.Path = sPath;

            // Make sure you use the OR on each Filter because we need to monitor
            // all of those activities

            FolderWatcher.NotifyFilter = System.IO.NotifyFilters.DirectoryName;

            FolderWatcher.NotifyFilter =
            FolderWatcher.NotifyFilter | System.IO.NotifyFilters.FileName;
            FolderWatcher.NotifyFilter =
            FolderWatcher.NotifyFilter | System.IO.NotifyFilters.Attributes;

            // Now hook the triggers(events) to our handler (eventRaised)
            FolderWatcher.Changed += new FileSystemEventHandler(eventRaised);
            FolderWatcher.Created += new FileSystemEventHandler(eventRaised);
            FolderWatcher.Deleted += new FileSystemEventHandler(eventRaised);

            // Occurs when a file or directory is renamed in the specific path
            // Todo: lbe: indeed we have to take care of that..
            //_watchFolder.Renamed += new System.IO.RenamedEventHandler(eventRenameRaised);

            // And at last.. We connect our EventHandles to the system API (that is all
            // wrapped up in System.IO)
            try
            {
                FolderWatcher.EnableRaisingEvents = true;
            }
            catch (ArgumentException)
            {
                //abortAcitivityMonitoring();
            }
        }


        private void OptionsForm_DragEnter(object sender, DragEventArgs e)
        {
            //If they are dragging a file, let the cursor reflect
            //the operation is permitted.
            if (e.Data.GetDataPresent(DataFormats.FileDrop, false))
            {
                e.Effect = DragDropEffects.Copy;
            }
        }

        private void LogoutButton_Click(object sender, EventArgs e)
        {
            mainForm.Logout();
            LoginButton.Enabled = true;
            LogoutButton.Enabled = false;
            Username.Enabled = true;
            Password.Enabled = true;
            //RefreshButton.Enabled = false;
            LoginButton.Text = "Login";
            UploaderStatus.Text = "Logged out.";
        }

        private void OptionsForm_Resize(object sender, EventArgs e)
        {
            //When minimizing, hide this form from the taskbar.
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                mainForm.HandleMinimize();
            }
        }

        private void DocList_SelectedIndexChanged(object sender, EventArgs e)
        {

        }

        private void browseFolder(string folder)
        {
            // Currently we won't do recurrent!
            //foreach (string strDirName in Directory.GetDirectories( folder))
            //{
            //    browseFolder(strDirName);
            //}

            foreach (string strFileName in Directory.GetFiles( folder))
            {
                pendingFiles.Items.Add( strFileName);
            }
        }

        private void buttonRemove_Click(object sender, EventArgs e)
        {
            browseFolder(@"D:\my\projects\Hill\");
        }





    }
}